home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Netware Super Library
/
Netware Super Library.iso
/
mis_util
/
dbfdir
/
dbfdir.prg
< prev
Wrap
Text File
|
1995-06-30
|
15KB
|
442 lines
*!*********************************************************************
*!
*! Source File: DBFDIR.PRG
*!
*! System: DBFDIR - Database directory
*! Author: John Wright
*! Copyright (c) 1993-1995 John Wright
*!
*! Procedures : Force_main
*!
*!*********************************************************************
* 07/20/93 - Modified DISPSTRU to emulate old DBDIR.COM with added
* support for FoxPro DBFs.
* 10/07/93 - Added support for dBase II files.
* 11/15/93 - Display DBF structure if /S specified.
* 11/16/93 - Check for FoxPro CDX reference.
* 02/06/94 - Changed to work with Force 2.4 new features/syntax.
* 06/30/95 - Better support for dBASE II files including structure list.
* Some old programs still use dBASE II files!!!
#INCLUDE date.hdr
#INCLUDE fileio.hdr
#INCLUDE string.hdr
#INCLUDE system.hdr
#INCLUDE io.hdr
#PRAGMA w_func_proc-
*!**********************************************
*!
*! Procedure Force_main
*!
*!Parameters : Type Method Name
*! : CHAR(127) REFERENCE cmd_line
*!
*!**********************************************
PROCEDURE Force_main
PARAMETERS CHAR(127) cmd_line
VARDEF
CHAR cr_lf
CHAR cPattern
CHAR cDbfPath
CHAR cDbfName
CHAR cText
CHAR(1) cVersion
CHAR(3) cLastUpdate
CHAR(1) cField
CHAR(1) cCDXbyte
* field info
CHAR(10) fld_name
CHAR(1) fld_type
CHAR(1) fld_len
CHAR(1) fld_dec
INT nHeader
INT nFields
INT nRecSize
INT nLoop
INT nSpot
LONG nRecs
UINT uHandle
UINT nError
LOGICAL lStructure
ENDDEF
cPattern := cmd_line
cr_lf := CHR(13)+CHR(10)
cText := "DBFDIR v1.4 - Database Directory "+;
"(c) 1993-1995 John Wright"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
FB_WRITE(&STD_OUT,cr_lf,2)
IF "/?" $ cPattern
cText := "Display a DBF directory list or file structures."+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " "+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "Syntax: DBFDIR [<pattern>] [/S] "+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " "+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " Start Size Contents of DBF header"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " ----- ---- ----------------------"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 0 1 Database version (see list below)"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 1 3 Date of last update"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 4 4 Last record (number of records)"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 8 2 Offset where data starts"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 9 2 Record size"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 11 20 Filler "+;
"(FoxPro DBFs may contain CDX reference)"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " "+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " DEC File type HEX"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " --- --------------------- ---"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 02 dBASE II 02"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " Valid: 03 dBASE III/Clipper/Fox 03"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " DBF 04 dBASE IV 04"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " ver. 131 dBASE III with Memos 83"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 139 dBASE IV with Memos 8B"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := " 245 FoxPro with Memos F5"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
QUIT
ENDIF
cPattern := UPPER(LTRIM(RTRIM(cPattern))) + " "
IF "/S" $ cPattern
lStructure := .T.
nLoop := AT( "/S", cPattern )
cText := SUBSTR( cPattern, 1, nLoop-1 )
cText += SUBSTR( cPattern, nLoop+2, LEN(cPattern)-2 )
cPattern := LTRIM(cText)
ELSE
lStructure := .F.
ENDIF
IF cPattern := " "
cPattern := "*.DBF"
ENDIF
* Save path if specified (FIND_FSTR only returns the file name)
DO CASE
CASE "\" $ cPattern
cDbfPath := UPPER(SUBSTR(cPattern,1,RAT("\",cPattern)))
CASE ":" $ cPattern
cDbfPath := UPPER(SUBSTR(cPattern,1,RAT(":",cPattern)))
OTHERWISE
cDbfPath := ""
ENDCASE
* search for matching file(s)
IF .NOT. FIND_FIRST( cPattern, 0x20 )
cText := "ERROR: No files found matching => "+cPattern+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
FB_WRITE(&STD_OUT,cr_lf,2)
QUIT
ENDIF
IF .NOT. lStructure
cText := "Database name Records Last Update Filesize "
cText += "RecLen Fields Memo Ver"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
ENDIF
REPEAT
* Reset counters and flags
cVersion := " "
cCDXbyte := " "
nFields := 0
nHeader := 0
nRecSize := 0
nRecs := 0
cDbfName := cDbfPath+FIND_FSTR()
IF .NOT. FB_OPEN( uHandle, cDbfName, &B_READ )
cText := "ERROR: Cannot open file => "+cDbfName+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
LOOP
ELSE
cText := SUBSTR( FIND_FSTR() + SPACE(12), 1, 12 )
ENDIF
* Look for CDX reference
FB_SEEK(uHandle,28,&FB_BEGIN)
FB_READ(uHandle,cCDXbyte,1)
* Get the database version - first character
FB_SEEK(uHandle,0,&FB_BEGIN)
FB_READ(uHandle,cVersion,1)
IF cVersion $ "âï⌡"
* dBase III compatible file
IF cVersion <> ""
* Date of last update stored as three digit character string
FB_SEEK(uHandle,1,&FB_BEGIN)
FB_READ(uHandle,cLastUpdate,3)
* Number of records stored as four digit binary number
FB_SEEK( uHandle, 4, &FB_BEGIN )
FB_READ( uHandle, nRecs, 4 )
* Header size
FB_SEEK( uHandle, 8, &FB_BEGIN )
FB_READ( uHandle, nHeader, 2 )
* Header prologue is 33 and fields are 32 each
nFields := ( nHeader - 33 ) / 32
* Record size
FB_SEEK( uHandle, 10, &FB_BEGIN )
FB_READ( uHandle, nRecSize, 2 )
IF lStructure
cText := "Name of database file: "+FIND_FSTR()+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "Number of records: "+;
LTRIM(STR( nRecs, 12, 0 )) + cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "Date of last update: "+;
RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,2,1)),2,0)),2)+"/"+;
RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,3,1)),2,0)),2)+"/"+;
STR(ASC(SUBSTR(cLastUpdate,1,1)),2,0) + cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
IF cCDXbyte = ""
cText := "CDX reference found!" + cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
ENDIF
cText := "Field Field name Type Width Dec"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
* process the DBF header
fld_name := " "
FOR nLoop := 1 TO nFields
nSpot := (nLoop*32)
FB_SEEK(uHandle,nSpot,&FB_BEGIN)
* get field name and check first character
FB_READ(uHandle,fld_name,10)
* CHR(13) means end of field definitions
IF SUBSTR(fld_name,1,1) <> CHR(13)
* Gobble up an extra character ...
FB_READ(uHandle,fld_type,1)
* field type - 11th position
FB_READ(uHandle,fld_type,1)
fld_type := SUBSTR(fld_type,1,1)
* field length - 16th position
nSpot := (nLoop*32)+16
FB_SEEK(uHandle,nSpot,&FB_BEGIN)
FB_READ(uHandle,fld_len,1)
* field decimal - 17th position
FB_READ(uHandle,fld_dec,1)
* print the field and continue
cText := STR(nLoop,5,0)+" "+;
SUBSTR(fld_name+SPACE(12),1,12)
DO CASE
CASE fld_type = "C"
cText += "Character"
CASE fld_type = "D"
cText += "Date "
CASE fld_type = "L"
cText += "Logical "
CASE fld_type = "M"
cText += "Memo "
CASE fld_type = "N"
cText += "Numeric "
OTHERWISE
cText += "unknown "
ENDCASE
cText += STR(ASC(fld_len),8,0)
IF fld_type = "N"
cText += STR(ASC(fld_dec),6,0)
ENDIF
IF fld_type = "M"
* Type of memo
DO CASE
CASE cVersion $ "â"
cText += " DB3"
CASE cVersion $ "ï"
cText += " DB4"
CASE cVersion $ "⌡"
cText += " Fox"
ENDCASE
ENDIF
cText += cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
ENDIF
NEXT
cText := "** Total **"+STR(nRecSize,25,0)+cr_lf
ELSE
cText += STR( nRecs, 12, 0 )
cText += " "+;
RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,2,1)),2,0)),2)+"/"+;
RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,3,1)),2,0)),2)+"/"+;
STR(ASC(SUBSTR(cLastUpdate,1,1)),2,0)
ENDIF
ELSE
* Number of records in dBASE II header
FB_SEEK( uHandle, 1, &FB_BEGIN )
FB_READ( uHandle, nRecs, 2 )
cText += STR( nRecs, 12, 0 )
* Record size
FB_SEEK( uHandle, 6, &FB_BEGIN )
FB_READ( uHandle, nRecSize, 1 )
* dBase II file structure is different...
IF lStructure
cText := "Name of database file: "+FIND_FSTR()+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "Number of records: "+;
LTRIM(STR( nRecs, 12, 0 ))+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "Field Field name Type Width Dec"+cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
ELSE
* Don't know last update for dBase II files
cText += " " + DTOC( FIND_FDATE() )
ENDIF
* Figure out the number of fields (max = 32)
nFields := 0
FOR nLoop := 1 TO 32
* Position to field start
nSpot := 8 + ( (nLoop-1) * 16 )
FB_SEEK(uHandle,nSpot,&FB_BEGIN)
* Read field name
FB_READ(uHandle,fld_name,10)
* Check if a valid field name
IF AT( SUBSTR(fld_name,1,1), CHR(13)+CHR(0) ) > 0
EXIT
ELSE
nFields ++
ENDIF
IF lStructure
* print field and continue
cText := STR(nFields,5,0)+" "
cText += SUBSTR(fld_name+SPACE(12),1,12)
* Gobble up an extra character ...
FB_READ(uHandle,fld_type,1)
* Read field type
FB_READ(uHandle,fld_type,1)
DO CASE
CASE fld_type = "C"
cText += "Character"
CASE fld_type = "D"
cText += "Date "
CASE fld_type = "L"
cText += "Logical "
CASE fld_type = "M"
cText += "Memo "
CASE fld_type = "N"
cText += "Numeric "
OTHERWISE
cText += "unknown "
ENDCASE
* field length
FB_READ(uHandle,fld_len,1)
cText += STR(ASC(fld_len),8,0)
* field decimal (?)
FB_READ(uHandle,fld_dec,1)
IF fld_type = "N"
cText += STR(ASC(fld_dec),6,0)
ENDIF
cText += cr_lf
FB_WRITE(&STD_OUT,cText,LEN(cText))
cText := "** Total **"+STR(nRecSize,25,0)+cr_lf
ENDIF
NEXT
ENDIF
IF .NOT. lStructure
* File size
cText += STR( FIND_FSIZE(), 12, 0 )
* Record size
cText += STR( nRecSize, 8, 0 )
* Number of fields
cText += STR( nFields, 8, 0 ) + " "
* Does file have memo fields?
IF cVersion $ "âï⌡"
cText += "Yes "
ELSE
cText += "No "
ENDIF
* Type of file
DO CASE
CASE cVersion $ ""
cText += "dB2"
CASE cVersion $ "â"
cText += "dB3"
CASE cVersion $ "ï"
cText += "dB4"
CASE cVersion $ "⌡"
cText += "Fox"
ENDCASE
IF cCDXbyte = ""
cText += "+CDX"
ENDIF
ENDIF
ELSE
cText += " ** Unrecognized database type **"
ENDIF
FB_WRITE(&STD_OUT,cText,LEN(cText))
FB_WRITE(&STD_OUT,cr_lf,2)
FB_CLOSE(uHandle)
UNTIL .NOT. FIND_NEXT()
QUIT
ENDPRO
*: EOF: DBFDIR.PRG